<?php
// +----------------------------------------------------------------------
// | Author: July
// +----------------------------------------------------------------------
// | 创建时间: 2023-12-27 20:39:42
// +----------------------------------------------------------------------
// | UI创建控制器
// +----------------------------------------------------------------------

namespace july\julyadmin\admin\controller;

use july\julyadmin\builder\traits\HasBuilder;
use july\julyadmin\common\model;
use july\julyadmin\common\model\DatabaseManage as DatabaseManageModel;
use think\facade\Db;

class UiCreate extends Common
{
    use HasBuilder;

    public function __construct()
    {
        //重新初始化父类
        parent::initialize();
        //数据模型
        $this->dataModel = new DatabaseManageModel();
        //join关联查询的表信息如，['category'=>'inner','comment'=>'left']
        $this->relationWithJoins = [];
        //with预查询关联表信息，如category,comment
        $this->relationWiths = [];
        //页面标题
        $this->pageTitle = 'UI生成';
        //允许表格行内编辑的字段,如name,sex
        $this->allowRowEditField = [];
        //不允许删除的主键数组，如1,2,3
        $this->noDeletePrimarykeys = [];
        //不允许编辑的主键数组，如1,2,3
        $this->noEditPrimarykeys = [];
        //不允许禁用的主键数组，如1,2,3
        $this->noDisabledPrimarykeys = [];
        //下拉join关联查询的表信息如，['category'=>'inner','comment'=>'left']
        $this->selectRelationWithJoins = [];
        //下拉with预查询关联表信息，如category,comment
        $this->selectRelationWiths = [];
        //下拉列表默认查询条件，如 [['disabled', '=', 1]]，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectWhere = [];
        //下拉列表模糊查询字段,如 'name|title'，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
        $this->selectSearch = '';
        //下拉列表默认 Text 字段 如 '{id}#{nickname}'或者'id:{id}-名称:{name}'，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
        $this->selectTextField = '';
        //下拉默认id字段,如：id
        $this->selectIdField = 'id';
        //下拉列表查询时的字段，如：id,name，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.，当前表可以不加
        $this->selectFields = 'id,name';
        //下拉列表父id字段，如：parent_id，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectParentId = 'parent_id';
        //下拉列表查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果有配置了$this->SelectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectOneParentWhere = [];
        //下拉列表查询排序，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectOrder = '';
        //列表排序，如果有配置了$this->relationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->sort = 'id desc';
        //父id字段名称，如parent_id,当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候需要指定父级字段名称，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.，根据实际需求修改
        $this->parentField = '';
        //查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果有配置了$this->relationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->oneParentWhere = [];
        //表格类型,table,treeTable
        $this->tableType = 'table';
        //树形表格分组字段，比如name，那么展开和搜索箭头就会在name这一列显示，当表格为treeTable的时候会用到
        $this->treeTableGroupField = '';
        //需要合计的字段，如['显示在哪个字段','显示哪个字段的值']，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如['id'=>'admin.sex','money'=>admin.money']
        $this->totalRow = [];
        //设置主键
        $this->pk = 'id';
    }

    //不需要登录验证的控制器和方法，如：['index']
    protected $noNeedLogin = [];
    //不需要权限验证的控制器和方法，如：['index']
    protected $noPermissionAuth = [];
    //允许出现长度的类型
    protected $alloow_use_length_types = [
        'tinyint'    => 'tinyint',
        'smallint'   => 'smallint',
        'mediumint'  => 'mediumint',
        'int'        => 'int',
        'bigint'     => 'bigint',
        'float'      => 'float',
        'double'     => 'double',
        'decimal'    => 'decimal',
        'char'       => 'chart',
        'varchar'    => 'varchar',
        'tinytext'   => 'tinytext',
        'text'       => 'text',
        'mediumtext' => 'mediumtext',
        'binary'     => 'binary',
        'varbinary'  => 'varbinary',
    ];
    //支持的字段类型
    protected $types = [
        'tinyint'    => 'tinyint',
        'smallint'   => 'smallint',
        'mediumint'  => 'mediumint',
        'int'        => 'int',
        'bigint'     => 'bigint',
        'float'      => 'float',
        'double'     => 'double',
        'decimal'    => 'decimal',
        'char'       => 'chart',
        'varchar'    => 'varchar',
        'tinytext'   => 'tinytext',
        'text'       => 'text',
        'mediumtext' => 'mediumtext',
        'longtext'   => 'longtext',
        'binary'     => 'binary',
        'varbinary'  => 'varbinary',
        'tinyblob'   => 'tinyblob',
        'longblob'   => 'longblob',
        'blob'       => 'blob',
        'mediumblob' => 'mediumblob',
        'date'       => 'date',
        'time'       => 'time',
        'datetime'   => 'datetime',
        'timestamp'  => 'timestamp',
        'json'       => 'json',
    ];

    //表格字段生成类型
    protected $form_create_type = [
        'text'           => 'text',
        'number'         => 'number',
        'date'           => 'date',
        'textarea'       => 'textarea',
        'datetime-local' => 'datetime-local',
        'month'          => 'month',
        'time'           => 'time',
        'week'           => 'week',
        'color'          => 'color',
        'email'          => 'email',
        'select'         => 'select',
        'multipleSelect' => 'multipleSelect',
        'switchBtn'      => 'switchBtn',
        'checkbox'       => 'checkbox',
        'radio'          => 'radio',
        'password'       => 'password',
        'ueditor'        => 'ueditor',
        'html'           => 'html',
        'iconPicker'     => 'iconPicker',
        'tags'           => 'tags',
        'jsTree'         => 'jsTree',
        'image'          => 'image',
        'file'           => 'file',
        'items'          => 'items',
        'hidden'         => 'hidden',
        'gaodeMap'       => 'gaodeMap',
        'editorMd'       => 'editorMd'
    ];

    /**
     * 设置当前页面
     * @Author   July
     * @DateTime 2024-01-13T19:41:56+0800
     * @param    $table 表格
     */
    protected function buildPage(&$table = [])
    {
        //搜索
        $table->getSearch()
            ->show('text', 'keyword', '表名/备注')->placeholder('表名/备注');

        //表格工具栏
        $updateTablesUrl = url('DatabaseManage/updateTables');
        $clearDataUrl    = url('DatabaseManage/clearData');

        $table->getToolbar()
            ->refreshBtn();

        //表格数据
        $table->showCheckbox(false);
        $table->show('id', 'ID')->width(80)->sort(true);
        $table->show('name', '表名')->width(300)->sort(true);
        $table->show('engine', '引擎')->width(90)->sort(true);
        $table->show('charset', '编码')->width(80)->sort(true);
        $table->show('comment', '备注');

        //表格右侧操作列
        $table->showRowHandleMenus()->width(80);
        $table->getTableRowBtns()
            ->openWindowBtn('add', '生成控制器', url('UiCreate/add'), '', '', '98%', '98%');

    }

    /**
     * 处理数据
     * 因为查询出来的数据可能需要二次处理
     * @Author   July
     * @DateTime 2024-01-13T19:44:46+0800
     * @param  array   &$data 查询出来的数据
     */
    protected function handleData(&$data = [])
    {

    }

    /**
     * 处理查询条件
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param array $search  查询条件
     * @return  array $where
     */
    protected function filterWhere($search = [])
    {
        $where = [];
        foreach ($search as $k => $v) {
            if ($v === "") {
                continue;
            }
            switch ($k) {
                case "keyword":
                    $where[] = ['name|comment', 'like', '%' . $v . '%'];
                    break;
            }
        }

        return $where;
    }

    /**
     * 处理下拉列表查询条件
     * @Author   July
     * @DateTime 2024-01-13T19:47:05+0800
     * @param  array $where  现有的查询条件
     * @return array
     */
    protected function filterSelectPageWhere($where = [])
    {

        return $where;
    }

    /**
     * 处理合计行信息
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param    array                   $where    已经处理过的最终查询条件，可以自己覆盖，用来自己重新查询数据
     * @param    integer                 $limit    每页多少条
     * @param    string                  $sort     排序
     * @param    integer                 $page     第几页
     * @param    array                   $totalRow 已经查询出来的合计信息，可以自己覆盖返回
     * @return   array                   $totalRow 将处理过的最终信息返回
     */
    protected function filterTotalRow($where = [], $limit = 20, $sort = '', $page = 1, $totalRow = [])
    {
        return $totalRow;
    }

    /**
     * @Author   July
     * @DateTime 2024-01-13T19:49:03+0800
     * @param    Object                   &$form  form对象
     * @param    integer                  $isEdit 是否是编辑：0否，1是
     * @param    array                    &$data  当前这条数据的内容
     */
    protected function buildForm(&$form, $isEdit, &$data = [])
    {
        $pk       = input("get." . $this->getPk());
        $database = Config("database.connections.mysql.database");
        $find     = $this->dataModel->where([$this->getPk() => $pk])->find();

        //设置表单整体宽度为最大12
        $form->setColWidth(12);
        //设置标题宽度为2，设置表单元素宽度为10
        $form->size(2, 10);
        $form->pk                    = $this->getPk();
        $data                        = [];
        $data['controller_position'] = 'app/admin/controller';
        $data['controller_name']     = $this->camelize(substr_replace($find['name'], '', 0, strlen(Config('database.connections.mysql.prefix')))) . '.php';
        $data['model_position']      = 'app/common/model';
        $data['model_name']          = $this->camelize(substr_replace($find['name'], '', 0, strlen(Config('database.connections.mysql.prefix')))) . '.php';
        $create_time                 = date('Y-m-d H:i:s');
        $data['controller_desc']     = <<<EOT

// +----------------------------------------------------------------------
// | Author:
// +----------------------------------------------------------------------
// | 创建时间: {$create_time}
// +----------------------------------------------------------------------
// | {$find['comment']}
// +----------------------------------------------------------------------

EOT;
        //获取当前数据表所有字段
        $fields                 = [];
        $fields_list            = Db::query("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='{$database}' AND TABLE_NAME='{$find['name']}' ORDER BY ORDINAL_POSITION ASC");
        $is_parent              = false;
        $data['disabled_field'] = '';
        $data['width']          = 0;
        foreach ($fields_list as $k => $v) {
            $fields[$v['COLUMN_NAME']] = $v['COLUMN_NAME'];
            if ($v['COLUMN_NAME'] == 'parent_id') {
                $is_parent = true;
                if ($this->getRelationWithJoins($find)) {
                    $prefix       = Config('database.connections.mysql.prefix');
                    $table_prefix = substr_replace($find['name'], '', 0, strlen($prefix)) . '.';

                    $data['parent_id']      = $table_prefix . 'parent_id';
                    $data['oneParentWhere'] = '[[\'' . $table_prefix . 'parent_id\', \'=\',0]]';
                } else {
                    $data['parent_id']      = 'parent_id';
                    $data['oneParentWhere'] = '[[\'' . $table_prefix . 'parent_id\', \'=\',0]]';
                }

                $data['treeTableGroupField'] = 'parent_id';
            }
            //如果是disabled字段，就说明有禁用开启
            if ($v['COLUMN_NAME'] != 'disabled') {
                $data['disabled_field'] = 'disabled';
            }
        }

        $form->data = $data;
        $types      = $this->types;
        $form->show('text', 'controller_position', '控制器位置')->required()->help('不可乱填，同时也会是控制器命名空间，必须按照ThinkPHP框架要求填写。');
        $form->show('html', 'controller_name', '控制器名称');
        $form->show('text', 'model_position', '模型位置')->required()->help('不可乱填，同时也会是模型命名空间和模型位置，需要和模型创建的位置一致。');
        $form->show('html', 'model_name', '模型名称');
        $form->show('text', 'page_title', '页面名称')->default($find['comment'])->required()->help('页面左上角名称，如：会员管理');
        $form->show('textarea', 'controller_desc', '控制器注释')->rows(10)->maxlength(10000);

        $table_items         = [];
        $form_items          = [];
        $create_type_options = [
            'tinyint'    => 'number',
            'smallint'   => 'number',
            'mediumint'  => 'number',
            'int'        => 'number',
            'bigint'     => 'number',
            'float'      => 'number',
            'double'     => 'number',
            'decimal'    => 'number',
            'char'       => 'text',
            'varchar'    => 'text',
            'tinytext'   => 'text',
            'text'       => 'text',
            'mediumtext' => 'text',
            'longtext'   => 'text',
            'binary'     => 'text',
            'varbinary'  => 'text',
            'tinyblob'   => 'text',
            'longblob'   => 'text',
            'blob'       => 'text',
            'mediumblob' => 'text',
            'date'       => 'month',
            'time'       => 'time',
            'datetime'   => 'datetime-local',
            'timestamp'  => 'number',
            'json'       => 'text',
        ];
        foreach ($fields_list as $dfk => $dfv) {
            $table_field_attr = [];
            $form_field_attr  = [];
            //如果字段是删除字段，那么默认不生成
            if ($dfv['COLUMN_NAME'] != 'delete_time') {
                $table_field_attr[] = 'create';
                $form_field_attr[]  = 'create';
            }
            //如果字段是无符号，那么默认勾选排序和搜索
            if (stripos(strtolower($dfv['COLUMN_TYPE']), 'unsigned') > -1) {
                $table_field_attr[] = 'sort';
                $table_field_attr[] = 'search';
            }
            //如果字段是无符号并且字段是id，或者字段是id，那么默认勾选主键
            if ((stripos(strtolower($dfv['COLUMN_TYPE']), 'unsigned') > -1 && $dfv['COLUMN_NAME'] == 'id') || $dfv['COLUMN_NAME'] == 'id') {
                $table_field_attr[] = 'primary_key';
            }

            //如果字段类型包含char那么默认勾选排序和搜索
            if (stripos(strtolower($dfv['COLUMN_TYPE']), 'char') > -1) {
                $table_field_attr[] = 'sort';
                $table_field_attr[] = 'search';
            }

            //如果字段包含create_time,update_time，默认勾选排序和搜索
            if (in_array($dfv['COLUMN_NAME'], ['create_time', 'update_time'])) {
                $table_field_attr[] = 'sort';
                $table_field_attr[] = 'search';
            }

            //如果字段不是时间字段，默认添加创建属性勾选
            if (strtolower($dfv['COLUMN_TYPE']) != 'datetime') {
                $form_field_attr[] = 'add_create';
            }
            //表格字段列表
            $width = '';
            if (strtolower($dfv['COLUMN_TYPE']) == 'datetime') {
                $width = 180;
            } else if (stripos(strtolower($dfv['COLUMN_TYPE']), 'int(') !== false) {
                $where   = [];
                $where[] = ['table_name', '=', $find['name']];
                $where[] = ['field', '=', $dfv['COLUMN_NAME']];
                $withs   = model\ModelRelation::where($where)->count();
                if ($withs) {
                    $table_field_attr[] = 'sort';
                    $table_field_attr[] = 'search';
                    $width              = 200;
                } else {
                    $width = 100;
                }
            } else if (stripos(strtolower($dfv['COLUMN_TYPE']), 'tinyint(') !== false) {
                $width = 80;
            } else if (stripos(strtolower($dfv['COLUMN_TYPE']), 'date(') !== false) {
                $width = 100;
            } else {
                $width = 200;
            }
            $table_items[] = [
                'field'       => $dfv['COLUMN_NAME'],
                'type'        => $dfv['COLUMN_TYPE'],
                'comment'     => $dfv['COLUMN_COMMENT'],
                'attr'        => $table_field_attr,
                'create_type' => isset($create_type_options[$dfv['DATA_TYPE']]) ? $create_type_options[$dfv['DATA_TYPE']] : '',
                'to'          => '',
                'DATA_TYPE'   => $dfv['DATA_TYPE'],
                'width'       => $width,
            ];

            //表单下拉选项信息
            $options = '';
            //表单字段下拉请求信息
            $dataUrl = '';
            //查询当前字段有没有被其它表关联，有的话下拉参数默认生成
            $where   = [];
            $where[] = ['table_name', '=', $find['name']];
            $where[] = ['field', '=', $dfv['COLUMN_NAME']];
            $withs   = model\ModelRelation::where($where)->find();
            if ($withs) {
                $prefix                 = Config('database.connections.mysql.prefix');
                $relationControllerName = substr_replace($withs['relation_table'], '', 0, strlen($prefix));
                $relationControllerName = $this->camelize($relationControllerName);
                $dataUrl                = 'url(\'' . $relationControllerName . '/selectPage\')';
            }

            if ($dfv['COLUMN_NAME'] == 'id') {
                //如果字段是id，默认创建类型为隐藏
                $create_type = 'hidden';
            } else if (strtolower($dfv['COLUMN_TYPE']) == 'tinyint(1)') {
                //如果字段类型为tinyint(1)很大可能是开关，所以创建类型默认为开关
                $create_type = 'switchBtn';
            } else if ($dfv['COLUMN_TYPE'] == 'datetime' && !in_array('add_create', $form_field_attr)) {
                //如果字段类型是日期时间格式，并且添加时不创建，很大可能就是添加和更新字段，所以创建类型设为html
                $create_type = 'html';
            } else {
                $create_type = isset($create_type_options[$dfv['DATA_TYPE']]) ? $create_type_options[$dfv['DATA_TYPE']] : '';
            }

            //表单字段列表
            $form_items[] = [
                'field'       => $dfv['COLUMN_NAME'],
                'title'       => $dfv['COLUMN_COMMENT'],
                'type'        => $dfv['COLUMN_TYPE'],
                'attr'        => $form_field_attr,
                'create_type' => $create_type,
                'options'     => $options,
                'dataUrl'     => $dataUrl,
            ];
        }

        //表格字段生成类型
        $table_create_type = [
            'image'     => 'image',
            'switchBtn' => 'switchBtn',
        ];

        //表格字段编辑类型
        $table_edit_type = [
            'text'           => 'text',
            'number'         => 'number',
            'date'           => 'date',
            'datetime-local' => 'datetime-local',
            'month'          => 'month',
            'time'           => 'time',
            'week'           => 'week',
            'color'          => 'color',
            'email'          => 'email',
            'switchBtn'      => 'switchBtn',
        ];

        $form->show('radio', 'table_type', '表格类型')->itemsTitleStyle('width:410px;text-align:center;')->default($is_parent == false ? 'table' : 'treeTable')->required()->options([
            'table'     => '普通表格',
            'treeTable' => '树形表格',
        ])->when('treeTable',
            $form->show('text', 'parent_id', '树形表格父id字段名')->default($data['parent_id'] ?? '')->help('父id字段名称，如parent_id,当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候需要指定父级字段名称，如果模型关联中有关联类型为[inner,left,right]的，排序字段需要带上表名加一个点，如admin.，根据实际需求修改'),

            $form->show('text', 'oneParentWhere', '查询树形表格第一层查询条件')->default($data['oneParentWhere'] ?? '')->help('查询第一层数据列表条件，如[[\'parent_id\',\'=\',\'0\']],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果模型关联中有关联类型为[inner,left,right]的，排序字段需要带上表名加一个点，如admin.'),

            $form->show('text', 'treeTableGroupField', '树形表格分组字段')->default($data['treeTableGroupField'] ?? '')->help('树形表格分组字段，比如name，那么展开和搜索箭头就会在name这一列显示，当表格为树形表格的时候会用到。')
        );

        $form->show('checkbox', 'toolbar', '表格工具栏')->options([
            'add'      => '添加',
            'edit'     => '编辑',
            'view'     => '详情',
            'disabled' => '禁用/开启',
            'delete'   => '删除',
            'print'    => '打印',
            'export'   => '导出',
            'import'   => '导入',
        ]);
        $form->show('checkbox', 'row_toolbar', '表格行操作')->options([
            'edit'     => '编辑',
            'view'     => '详情',
            'disabled' => '禁用/开启',
            'delete'   => '删除',
        ]);
        $form->show('text', 'disabled_field', '禁用/启用字段名称')->help('禁用/启用的字段名称：如果当前表的禁用启用字段是disabled，那么就写disabled，如果不需要就不写。');
        $form->show('items', 'table_fields', '表格字段')->default($table_items)->showRowHandleMenus(false)->style('min-width:1500px;')
            ->with(function ($form) use ($types, $table_create_type, $table_edit_type) {
                $form->show('hidden', 'DATA_TYPE', '数据类型');
                $form->show('text', 'field', '字段名')->readonly()->itemsTitleStyle('width:200px;text-align:center;')->required();
                $form->show('html', 'type', '字段类型')->itemsTitleStyle('width:130px;text-align:center;')->readonly();
                $form->show('text', 'comment', '注释')->itemsTitleStyle('width:200px;text-align:center;')->required();
                $form->show('checkbox', 'attr', '属性')->itemsTitleStyle('width:410px;text-align:center;')->options([
                    'sort'        => '排序',
                    'search'      => '搜索',
                    'create'      => '生成',
                    'primary_key' => '主键',
                ]);
                $form->show('number', 'width', '列宽')->itemsTitleStyle('width:140px;text-align:center;')->tips('列宽度,不写则自适应');
                $form->show('select', 'create_type', '生成类型')->itemsTitleStyle('width:200px;text-align:center;')->options($table_create_type)->tips('不选择则显示纯文本');
                $form->show('select', 'edit_type', '编辑类型')->itemsTitleStyle('width:200px;text-align:center;')->options($table_edit_type)->tips('不选择则表格将不可以编辑。');
                $form->show('text', 'to', '显示内容')->itemsTitleStyle('min-width:200px;text-align:center;')->tips('比如这个字段是member_id，模型关联的是member表，并且关联名称为member，这里可以写{member.nickname}或者{member.username}{member.id}之类的，那么显示的就是对应关联模型member表的数据，也可以直接写{name}，那么显示的就是当前表的name，如果不填，那么显示的就是当前字段的值。');
            })->required();

        $form->show('switchBtn', 'create_form', '生成表单')->default('1');
        $form->show('radio', 'layout_type', '布局类型')->default('one_column')->options([
            'one_column'  => '一列',
            'two_columns' => '左右各一列',
        ])->help('当布局类型为一列时，所有表单组件全部为一列显示，当布局类型为左右各一列时，表单会分为左边一列，右边一列显示，如果表单没有勾选是左列还是右列则默认放到左列显示。');

        $form->show('items', 'form_fields', '表单字段')->default($form_items)->showRowHandleMenus(false)->style('min-width:1500px;')
            ->with(function ($form) use ($types) {
                $form->show('text', 'field', '字段名')->readonly()->itemsTitleStyle('width:200px;text-align:center;')->required();
                $form->show('text', 'title', '中文名')->itemsTitleStyle('width:200px;text-align:center;')->required();
                $form->show('html', 'type', '字段类型')->itemsTitleStyle('width:130px;text-align:center;')->readonly();
                $form->show('checkbox', 'attr', '属性')->itemsTitleStyle('width:260px;text-align:center;')->options([
                    'required'   => '必填',
                    'left'       => '左列',
                    'right'      => '右列',
                    'create'     => '创建',
                    'add_create' => '新增时创建',
                ])->tips('左列和右列，只有在布局类型为左右各一列时生效，如果创建不勾选，那么表单将不生成当前字段，如果新增时创建不勾选，那么在添加数据的时候则不显示字段，可用于添加修改时间的显示和不显示。');
                $form->show('number', 'maxlength', '最大字数')->itemsTitleStyle('width:130px;text-align:center;')->tips('最大输入字数，当创建类型为text/number/textarea/email/password时生效。');
                $form->show('select', 'create_type', '生成类型')->itemsTitleStyle('width:200px;text-align:center;')->options($this->form_create_type)->tips('不选择则不创建');
                $form->show('text', 'default', '默认值')->itemsTitleStyle('text-align:center;')->tips('1.生成类型为switchBtn时0为关闭1为开启<br>2.生成类型为items时无效，太复杂，不在这里做处理<br>3.生成类型为multipleSelect/select/checkbox/radio/tags/jsTree/file/image为:值1,值2，多个值用英文逗号分隔，也可以为[\'值1\',\'值2\']，其它的按照普通字符串输入即可。');
                $form->show('text', 'options', '参数')->itemsTitleStyle('text-align:center;')->tips('可不填，当生成类型为select/multipleSelect/checkbox/radio/switchBtn时生效，其中当生成类型为select/multipleSelect/checkbox/radio时格式如下<br>如：[\'1\'=>\'男\',\'2\'=>\'女\']<br>当生成类型为switchBtn时格式如下，如：[\'开启\',\'关闭\']，第一个参数是开关打开时的文字，第二个是关闭时的文字.');
                $form->show('text', 'dataUrl', '下拉请求地址')->itemsTitleStyle('text-align:center;')->tips('当生成类型为select/multipleSelect时生效，如：url(\'member/selectPage\')');
            })->required();
    }

    /**
     * 获取控制器配置参数
     * @Author   July
     * @DateTime 2023-10-09T21:11:58+0800
     * @param    array  $table  当前数据表信息
     * @param    array  $data   表单参数
     */
    private function getControllerSettings($table, $data = [])
    {
        //创建日期
        $DateTime = date("Y-m-d H:i:s");
        //允许行内编辑的字段列表
        $allowRowEditField = $this->getAllowRowEditField($data);
        if ($allowRowEditField) {
            array_walk($allowRowEditField, function (&$value, $key) {
                $value = "'" . $value . "'";
            });
            $allowRowEditField = implode(',', $allowRowEditField);
        } else {
            $allowRowEditField = '';
        }
        //获取允许搜索字段列表
        $allowSearchField = $this->getAllowSearchField($data);
        //获取父id字段
        $parentField = isset($data['parent_id']) && $data['parent_id'] !== '' ? $data['parent_id'] : '';
        //获取查询树形表格第一层查询条件
        $oneParentWhere = isset($data['oneParentWhere']) && $data['oneParentWhere'] !== '' ? $data['oneParentWhere'] : '[]';
        //获取树形表格分组字段名称
        $treeTableGroupField = isset($data['treeTableGroupField']) && $data['treeTableGroupField'] !== '' ? $data['treeTableGroupField'] : '';
        //表格右上角工具栏
        $tableRightTopToolbar = '';
        //获取主键字段
        $primary_key = $this->getPrimaryKey($data);
        //是否启用打印
        if (!isset($data['toolbar']) || !in_array('print', $data['toolbar'])) {
            $tableRightTopToolbar .= <<<EOT

        //隐藏右上角打印按钮
        \$table->printShow(false);
EOT;
        }
        //是否启用导出
        if (!isset($data['toolbar']) || !in_array('export', $data['toolbar'])) {
            $tableRightTopToolbar .= <<<EOT

        //隐藏右上角导出按钮
        \$table->exportShow(false);
EOT;
        }
        //是否启用导入
        if (!isset($data['toolbar']) || !in_array('import', $data['toolbar'])) {
            $tableRightTopToolbar .= <<<EOT

        //隐藏右上角导入按钮
        \$table->importShow(false);
EOT;
        }
        //验证必要字段
        if ($data['table_type'] == 'treeTable') {
            if (!isset($data['parent_id']) || !$data['parent_id']) {
                $this->error('当表格类型为树形表格的时候，"父id字段名称"不能为空');
            }

            if (!isset($data['oneParentWhere']) || !$data['oneParentWhere']) {
                $this->error('当表格类型为树形表格的时候，"查询树形表格第一层查询条件"不能为空');
            }

            if (!isset($data['treeTableGroupField']) || !$data['treeTableGroupField']) {
                $this->error('当表格类型为树形表格的时候，"树形表格分组字段"不能为空');
            }
        }

        //创建搜索表单代码
        $search = $this->createSearchForm($table, $data);
        //创建搜索条件传入代码
        $where = $this->createSearchWhere($table, $data);
        //创建表格工具栏代码
        $toolbar = $this->createToolbar($data);
        //生成表格数据
        $table_fields = $this->createTableFields($data);
        //创建表格行操作按钮
        $tableRowBtns = $this->createTableRowBtns($data);
        //默认下拉查询条件
        $selectWhere = isset($data['disabled_field']) && $data['disabled_field'] ? '[\'disabled\', \'=\', 1]' : '';
        //获取表单生成代码
        $forms = $this->createForm($data);
        //获取保存所需验证信息
        $validate = $this->createSaveValidate($data);
        //控制器名称
        $modelName = $this->camelize(substr_replace($table['name'], '', 0, strlen(Config('database.connections.mysql.prefix')))) . 'Model';
        //获取join关联信息
        $relationWithJoins = $this->getRelationWithJoins($table);
        //获取with关联信息
        $relationWiths = $this->getRelationWiths($table);

        $config = <<<EOT
    use HasBuilder;
    //不需要登录验证的控制器和方法，如：['index','index']
    protected \$noNeedLogin = [];
    //不需要权限验证的控制器和方法，如：['index','index']
    protected \$noPermissionAuth = ['*'];

    public function __construct()
    {
        //重新初始化父类
        parent::initialize();
        //数据模型
        \$this->dataModel = new {$modelName}();
        //join关联查询的表信息如，['category'=>'inner','comment'=>'left']
        \$this->relationWithJoins = [{$relationWithJoins}];
        //with预查询关联表信息，如category,comment
        \$this->relationWiths = [{$relationWiths}];
        //页面标题
        \$this->pageTitle = '{$data['page_title']}';
        //禁止或者开启字段名称
        \$this->disabledField = '{$data['disabled_field']}';
        //允许表格行内编辑的字段,如name,sex
        \$this->allowRowEditField = [{$allowRowEditField}];
        //不允许删除的主键数组，如1,2,3
        //\$this->noDeletePrimarykeys = [];
        //不允许编辑的主键数组，如1,2,3
        //\$this->noEditPrimarykeys = [];
        //不允许禁用的主键数组，如1,2,3
        //\$this->noDisabledPrimarykeys = [];
        //下拉join关联查询的表信息如，['category'=>'inner','comment'=>'left']
        \$this->selectRelationWithJoins = [];
        //下拉列表默认查询条件，如 [['disabled', '=', 1]]
        \$this->selectWhere = [{$selectWhere}];
        //下拉列表模糊查询字段,如 'name|title'
        \$this->selectSearch = 'id|name';
        //下拉列表默认 Text 字段 如 '{id}#{nickname}'或者'id:{id}-名称:{name}'，如果有配置了\$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
        \$this->selectTextField = '{id}#{name}';
        //下拉默认id字段
        \$this->selectIdField = 'id';
        //下拉列表查询时的字段，如：id,name，如果有配置了\$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.，当前表可以不加
        \$this->selectFields = 'id,name';
        //下拉列表父id字段，如：parent_id，如果有配置了\$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        \$this->selectParentId = 'parent_id';
        //下拉列表查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果有配置了\$this->SelectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        //\$this->selectOneParentWhere = [];
        //下拉列表查询排序，如果有配置了\$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        //\$this->selectOrder = '';
        //列表排序，如果有配置了\$this->relationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        //\$this->sort = '';
        //父id字段名称，如parent_id,当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候需要指定父级字段名称，如果有配置了\$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.，根据实际需求修改
        \$this->parentField = '{$parentField}';
        //查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，根据实际需求修改
        \$this->oneParentWhere = {$oneParentWhere};
        //表格类型,table,treeTable
        \$this->tableType = '{$data['table_type']}';
        //树形表格分组字段，比如name，那么展开和搜索箭头就会在name这一列显示，当表格为treeTable的时候会用到
        \$this->treeTableGroupField = '{$treeTableGroupField}';
        //需要合计的字段，如['显示在哪个字段','显示哪个字段的值']，如果有配置了\$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如['id'=>'admin.sex','money'=>admin.money']
        //\$this->totalRow = [];
        //设置主键，默认是id
        //\$this->pk = '{$primary_key}';
    }


    /**
     * 设置当前页面
     * @Author
     * @DateTime {$DateTime}
     * @param    $table 表格
     */
    protected function buildPage(&\$table = [])
    {

        {$search}
        {$toolbar}

        //表格数据
        \$table->showCheckbox();
        {$table_fields}

        {$tableRightTopToolbar}

        //表格右侧操作列
        \$table->showRowHandleMenus()->width({$tableRowBtns['width']});

        {$tableRowBtns['toolbar']}
    }

    /**
     * 处理数据
     * 因为查询出来的数据可能需要二次处理
     * @Author
     * @DateTime {$DateTime}
     * @param  array   &\$data 查询出来的数据
     */
    protected function handleData(&\$data = [])
    {

    }

    /**
     * 处理查询条件
     * @Author
     * @DateTime {$DateTime}
     * @param   array \$search  查询条件
     * @return  array \$where
     */
    protected function filterWhere(\$search = [])
    {
        \$where = [];
        {$where}
        return \$where;
    }

    /**
     * 处理下拉列表查询条件
     * @Author
     * @DateTime {$DateTime}
     * @param  array \$where  现有的查询条件
     * @return array
     */
    protected function filterSelectPageWhere(\$where = [])
    {

        return \$where;
    }

    /**
     * 处理合计行信息
     * @Author
     * @DateTime {$DateTime}
     * @param    array                   \$where    已经处理过的最终查询条件，可以自己覆盖，用来自己重新查询数据
     * @param    integer                 \$limit    每页多少条
     * @param    string                  \$sort     排序
     * @param    integer                 \$page     第几页
     * @param    array                   \$totalRow 已经查询出来的合计信息，可以自己覆盖返回
     * @return   array                   \$totalRow 将处理过的最终信息返回
     */
    protected function filterTotalRow(\$where = [], \$limit = 20, \$sort = '', \$page = 1, \$totalRow = [])
    {
        return \$totalRow;
    }

    /**
     * @Author
     * @DateTime {$DateTime}
     * @param    Object                   &\$form  form对象
     * @param    integer                  \$isEdit 是否是编辑：0否，1是
     * @param    array                    &\$data  当前这条数据的内容
     */
    protected function buildForm(&\$form, \$isEdit, &\$data = [])
    {
        {$forms}
    }

    /**
     * 保存
     * @Author
     * @DateTime {$DateTime}
     * @param  integer \$isEdit 是否是编辑 0否，1是
     */
    protected function save(\$isEdit)
    {
        \$pk = input("get." . \$this->getPk());

        \$data = request()->only([
        {$validate['only']}
        ], 'post');

        try {
            validate([
            {$validate['validate']}
            ])->check(\$data);
        } catch (\\think\\exception\ValidateException \$e) {
            \$this->error(\$e->getError());
        }

        return \$this->doSave(\$isEdit, \$data, \$pk);
    }

EOT;
        return $config;

    }

    /**
     * 获取允许行内编辑的字段列表
     * @Author   July
     * @DateTime 2023-11-19T12:40:32+0800
     * @param    array                    $data 表单提交数据
     * @return   array                          返回结果，如[name,sort]
     */
    private function getAllowRowEditField($data = [])
    {
        if (!isset($data['table_fields']) || !$data['table_fields']) {
            $this->error('表单字段信息为空');
        }
        $allowRowEditField = [];
        foreach ($data['table_fields'] as $k => $v) {
            if (isset($v['edit_type']) && $v['edit_type']) {
                $allowRowEditField[] = $v['field'];
            }
        }
        return $allowRowEditField;
    }

    /**
     * 获取允许搜索字段列表列表
     * @Author   July
     * @DateTime 2023-11-19T12:40:32+0800
     * @param    array                    $data 表单提交数据
     * @return   string                         返回结果，如"[name,sort]"
     */
    private function getAllowSearchField($data = [])
    {
        if (!isset($data['table_fields']) || !$data['table_fields']) {
            $this->error('表单字段信息为空');
        }
        $allowSearchField = [];
        foreach ($data['table_fields'] as $k => $v) {
            if (isset($v['attr']) && in_array('search', $v['attr'])) {
                $allowSearchField[] = $v['field'];
            }
        }
        return $allowSearchField;
    }

    /**
     * 获取主键字段
     * @Author   July
     * @DateTime 2023-11-19T12:40:32+0800
     * @param    array                    $data 表单提交数据
     * @return   string                         返回结果，如"id"
     */
    private function getPrimaryKey($data = [])
    {
        if (!isset($data['table_fields']) || !$data['table_fields']) {
            $this->error('表单字段信息为空');
        }
        $primary_key = '';
        foreach ($data['table_fields'] as $k => $v) {
            if (isset($v['attr']) && in_array('primary_key', $v['attr'])) {
                if (!$primary_key) {
                    $primary_key = $v['field'];
                } else {
                    $this->error('主键字段只能有一个，比如勾选id字段为主键');
                }
            }
        }
        if ($primary_key == '') {
            $this->error('主键不能为空');
        }
        return $primary_key;
    }

    /**
     * 创建搜索表单
     * @Author   July
     * @DateTime 2023-11-19T15:10:53+0800
     * @param    array                    $table 当前数据表信息
     * @param    array                    $data  表单提交数据
     * @return   string                          生成的表单代码字符串
     */
    private function createSearchForm($table, $data = [])
    {
        $search = PHP_EOL . "//搜索" . <<<EOT

        \$table->getSearch()

EOT;
        if (!isset($data['table_fields']) || !$data['table_fields']) {
            $this->error('表单字段信息为空');
        }
        foreach ($data['table_fields'] as $k => $v) {
            $type = 'text';
            if ($v['DATA_TYPE'] == 'date') {
                $type = 'date';
            } else if ($v['DATA_TYPE'] == 'datetime') {
                $type = 'datetime-local';
            } else if (isset($v['create_type']) && $v['create_type'] == 'switchBtn') {
                $type = 'select';
            }
            if (isset($v['attr']) && in_array('search', $v['attr'])) {
                //查询搜索字段有没有模型关联信息，有点话那搜索组件就弄成下拉
                $relation = model\ModelRelation::where(['table_name' => $table['name'], 'field' => $v['field']])->find();
                if ($relation || $type == 'select') {
                    $type    = 'select';
                    $options = '[1 => $this->switchBtnText[0], 0 => $this->switchBtnText[1]]';
                    if (isset($v['create_type']) && $v['create_type'] == 'switchBtn') {
                        $search .= <<<EOT
            ->show('{$type}', '{$v['field']}', '{$v['comment']}')->options({$options})

EOT;
                    } else {
                        $prefix            = Config('database.connections.mysql.prefix');
                        $relationModelName = substr_replace($relation['relation_table'], '', 0, strlen($prefix));
                        $relationModelName = $this->camelize($relationModelName);
                        $search .= <<<EOT
            ->show('{$type}', '{$v['field']}', '{$v['comment']}')->dataUrl(url('{$relationModelName}/selectPage'))

EOT;
                    }

                } else {
                    if (in_array($v['DATA_TYPE'], ['date', 'datetime'])) {
                        $search .= <<<EOT
            ->show('{$type}', '{$v['field']}_start', '{$v['comment']}开始')
            ->show('{$type}', '{$v['field']}_end', '{$v['comment']}结束')

EOT;
                    } else {
                        $search .= <<<EOT
            ->show('{$type}', '{$v['field']}', '{$v['comment']}')

EOT;
                    }

                }
            }
        }
        $search = trim($search, PHP_EOL) . ";" . PHP_EOL;
        return $search;
    }

    /**
     * 创建搜索条件
     * @Author   July
     * @DateTime 2023-11-19T15:10:53+0800
     * @param    array                    $table 当前数据表信息
     * @param    array                    $data  表单提交数据
     * @return   string                          生成的搜索条件传递代码
     */
    private function createSearchWhere($table, $data = [])
    {

        if (!isset($data['table_fields']) || !$data['table_fields']) {
            $this->error('表单字段信息为空');
        }

        //查询模型关联的信息中有没有关联类型为inner，left，right的，有的话那么查询条件就要加上表名了
        $relation     = model\ModelRelation::where([['table_name', '=', $table['name']], ['relation_type', 'in', 'inner,left,right']])->find();
        $table_prefix = '';
        if ($relation) {
            $prefix       = Config('database.connections.mysql.prefix');
            $table_prefix = substr_replace($table['name'], '', 0, strlen($prefix)) . '.';
        }

        $where = '';
        foreach ($data['table_fields'] as $k => $v) {
            if (isset($v['attr']) && in_array('search', $v['attr'])) {
                if (in_array($v['DATA_TYPE'], ['date', 'datetime'])) {
                    $where .= <<<EOT

                case '{$v['field']}_start':
                    \$where[] = ['{$table_prefix}{$v['field']}', '>=', \$v];
                    break;

                case '{$v['field']}_end':
                    \$where[] = ['{$table_prefix}{$v['field']}', '<=', \$v];
                    break;

EOT;
                } else if (in_array($v['DATA_TYPE'], ['timestamp'])) {
                    $where .= <<<EOT

                case '{$v['field']}_start':
                    \$where[] = ['{$table_prefix}{$v['field']}', '>=', \$v];
                    break;

                case '{$v['field']}_end':
                    \$where[] = ['{$table_prefix}{$v['field']}', '<=', \$v];
                    break;

EOT;
                } else if (in_array($v['DATA_TYPE'], ['tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'float', 'double', 'decimal'])) {
                    $where .= <<<EOT

                case '{$v['field']}':
                    \$where[] = ['{$table_prefix}{$v['field']}', '=', \$v];
                    break;

EOT;
                } else {
                    $where .= <<<EOT

                case '{$v['field']}':
                    \$where[] = ['{$table_prefix}{$v['field']}', 'LIKE', '%' . \$v . '%'];
                    break;

EOT;
                }
            }
        }

        $where = <<<EOT

        foreach (\$search as \$k => \$v) {
            if (\$v === "") {
                continue;
            }
            switch (\$k) {
                {$where}
                default:

                break;
            }
        }
EOT;
        return $where;
    }

    /**
     * 创建表格工具栏表单
     * @Author   July
     * @DateTime 2023-11-19T15:10:53+0800
     * @param    array                    $data  表单提交数据
     * @return   string                          生成的表单代码字符串
     */
    private function createToolbar($data = [])
    {
        $toolbar = <<<EOT

        //表格工具栏
        \$table->getToolbar()

EOT;
        if (isset($data['toolbar']) && $data['toolbar']) {
            foreach ($data['toolbar'] as $k => $v) {
                if (in_array($v, ['add', 'edit', 'view', 'disabled', 'delete'])) {
                    $toolbar .= <<<EOT
            ->{$v}Btn()

EOT;
                }
            }
        }

        $toolbar .= <<<EOT
            ->refreshBtn();
EOT;
        return $toolbar;
    }

    /**
     * 创建表格字段数据
     * @Author   July
     * @DateTime 2023-11-19T15:10:53+0800
     * @param    array                    $data  表单提交数据
     * @return   string                          生成的表单代码字符串
     */
    private function createTableFields($data = [])
    {
        $fields = <<<EOT


EOT;
        if (!isset($data['table_fields']) || !$data['table_fields']) {
            $this->error('表单字段信息为空');
        }
        foreach ($data['table_fields'] as $k => $v) {
            //没有勾选创建的直接跳过
            if (!isset($v['attr']) || !in_array('create', $v['attr'])) {
                continue;
            }
            //创建类型
            $create_type = isset($v['create_type']) && $v['create_type'] ? ' ,\'' . $v['create_type'] . '\'' : '';
            //单元格编辑类型
            $edit_type = isset($v['edit_type']) && $v['edit_type'] ? '->edit(\'' . $v['edit_type'] . '\')' : '';
            //格式化显示
            $to = isset($v['to']) && $v['to'] ? '->to(\'' . $v['to'] . '\')' : '';
            //列宽度
            $width = isset($v['width']) && $v['width'] ? '->width(\'' . $v['width'] . '\')' : '';
            //排序
            $sort = isset($v['attr']) && in_array('sort', $v['attr']) ? '->sort(true)' : '';
            if (in_array($v['DATA_TYPE'], ['date', 'datetime'])) {
                $fields .= <<<EOT
        \$table->show('{$v['field']}', '{$v['comment']}'{$create_type}){$edit_type}{$to}{$width}{$sort};

EOT;
            } else {
                $fields .= <<<EOT
        \$table->show('{$v['field']}', '{$v['comment']}'{$create_type}){$edit_type}{$to}{$width}{$sort};

EOT;
            }
        }
        return $fields;
    }

    /**
     * 创建表格行操作按钮
     * @Author   July
     * @DateTime 2023-11-19T15:10:53+0800
     * @param    array                    $data  表单提交数据
     * @return   array                           ['toolbar' => $toolbar, 'width' => $width] 表格按钮代码和按钮列宽度
     */
    private function createTableRowBtns($data = [])
    {
        $width   = 0;
        $toolbar = PHP_EOL . "//表格行操作按钮" . <<<EOT

        \$table->getTableRowBtns()

EOT;
        if (isset($data['row_toolbar']) && $data['row_toolbar']) {
            foreach ($data['row_toolbar'] as $k => $v) {

                if (in_array($v, ['edit', 'view', 'disabled', 'delete'])) {
                    if ($v == 'disabled') {
                        $width += 70;
                    } else {
                        $width += 44;
                    }
                    $toolbar .= <<<EOT
            ->{$v}Btn()

EOT;
                }
            }
        }
        $toolbar = trim($toolbar, PHP_EOL) . ";" . PHP_EOL;
        return ['toolbar' => $toolbar, 'width' => $width];
    }

    /**
     * 创建表单代码
     * @Author   July
     * @DateTime 2023-12-17T13:42:48+0800
     * @param    array                    $data  表单提交数据
     * @return   string                          生成表单的代码
     */
    private function createForm($data = [])
    {
        if (!isset($data['create_form']) || $data['create_form'] != 1) {
            if (isset($data['toolbar']) && (in_array('add', $data['toolbar']) || in_array('edit', $data['toolbar']) || in_array('view', $data['toolbar']))) {
                $this->error('表格工具栏选择了【添加,编辑,详情】必须创建表单');
            }
            if (isset($data['row_toolbar']) && (in_array('edit', $data['row_toolbar']) || in_array('view', $data['row_toolbar']))) {
                $this->error('表格行操作选择了【编辑,详情】必须创建表单');
            }

            return '';
        }
        $layout_type = isset($data['layout_type']) ? $data['layout_type'] : 'one_column';

        if ($layout_type == 'one_column') {
            //生成一列表单
            $result = $this->createFormCode($data, 'center');
            return $result;
        } else {
            //生成两列表单
            $result = <<<EOT

            \$form->setColWidth(12);

EOT;

            $leftFrom = $this->createFormCode($data, 'left');
            $result .= <<<EOT

            \$form->leftStart(6);
            {$leftFrom}

            \$form->leftEnd();

EOT;

            $rightFrom = $this->createFormCode($data, 'right');
            $result .= <<<EOT

            \$form->rightStart(6);
            {$rightFrom}

            \$form->rightEnd();
EOT;
            return $result;
        }
    }

    /**
     * 验证创建表单的数据字段中是否有不可以存在的字符
     * @Author   July
     * @DateTime 2023-12-17T15:14:21+0800
     * @param    array                    $data 表单提交的数据
     * @return   boolean                        是否通过验证true,false
     */
    private function validateFromTitle($data = [])
    {
        foreach ($data['form_fields'] as $k => $v) {
            $str = str_replace("\'", "\单引号\单引号", $v["title"]);
            if (stripos($str, "'") !== false) {
                $this->error('中文名不能存在未转义单引号');
            }
            $str = str_replace("\'", "\单引号\单引号", $v["default"]);
            if (stripos($str, "'") !== false) {
                $this->error('默认值不能存在未转义单引号');
            }
            $str = str_replace("\'", "\单引号\单引号", $v["dataUrl"]);
            if (stripos($str, "'") !== false) {
                $this->error('下拉请求地址不能存在未转义单引号');
            }
        }
    }

    /**
     * 创建表单
     * @Author   July
     * @DateTime 2023-12-17T14:05:19+0800
     * @param    array                    $data 表单提交数据
     * @param    string                   $data 布局类型,center[一列],left[左边列],right[右边列]
     * @return   string                         表带代码
     */
    private function createFormCode($data = [], $layout_type = '')
    {
        $forms = '';
        foreach ($data['form_fields'] as $k => $v) {
            if ($layout_type === 'left' && (!isset($v['attr']) || !in_array('left', $v['attr']))) {
                continue;
            }
            if ($layout_type === 'right' && (!isset($v['attr']) || !in_array('right', $v['attr']))) {
                continue;
            }
            if (!isset($v['create_type']) || $v['create_type'] === '') {
                continue;
            }
            if (!isset($v['attr']) || !in_array('create', $v['attr'])) {
                continue;
            }
            $create_type = $v['create_type'];
            $title       = isset($v['title']) && $v['title'] ? $v['title'] : $v['field'];

            $form = <<<EOT

        \$form->show('{$create_type}', '{$v['field']}', '{$title}')
EOT;
            if (isset($v['attr']) && in_array('required', $v['attr'])) {
                $form .= '->required()';
            }

            if (isset($v['default']) && $v['default'] !== '') {
                $form .= '->default(\'' . $v['default'] . '\')';
            }

            if (isset($v['options']) && $v['options'] !== '' && in_array($create_type, ['select', 'multipleSelect', 'checkbox', 'radio'])) {
                $form .= '->options(' . $v['options'] . ')';
            }

            if (isset($v['dataUrl']) && $v['dataUrl'] !== '' && in_array($create_type, ['select', 'multipleSelect'])) {
                $form .= '->dataUrl(' . $v['dataUrl'] . ')';
            }

            if ($create_type == 'multipleSelect') {
                $from .= '->multiple()';
            }

            if (isset($v['maxlength']) && $v['maxlength'] > 0) {
                if (in_array($create_type, ['text', 'number', 'textarea', 'email', 'password'])) {
                    $form .= '->maxlength(\'' . $v['maxlength'] . '\')';
                }
            }

            if ($create_type == 'switchBtn' && isset($v['options']) && $v['options'] !== '') {
                $form .= '->switchBtnText(' . $v['options'] . ')';
            }
            $form .= ';';

            if (!isset($v['attr']) || !in_array('add_create', $v['attr'])) {
                $form = trim($form, PHP_EOL);
                $form = <<<EOT

        if(\$isEdit){
    {$form}
        }

EOT;
            }
            $forms .= $form;

        }
        return $forms;

    }

    /**
     * 创建保存所需验证代码
     * @Author   July
     * @DateTime 2023-12-17T14:33:45+0800
     * @param    array                    $data 表单提交的数据
     * @return   array                          ['only'=>'','validate'=>'']，返回允许提交的字段列表和验证信息列表，每个字段都是英文逗号分隔的
     */
    private function createSaveValidate($data = [])
    {
        if (!isset($data['create_form']) || $data['create_form'] != 1) {
            return ['only' => '', 'validate' => ''];
        }
        $only           = '';
        $validate       = '';
        $only_count     = 0;
        $validate_count = 0;
        foreach ($data['form_fields'] as $k => $v) {
            if (!isset($v['create_type']) || $v['create_type'] === '') {
                continue;
            }
            if ($only_count == 0) {
                $only .= <<<EOT
    '{$v['field']}',

EOT;
            } else {
                $only .= <<<EOT
            '{$v['field']}',

EOT;
            }
            $only_count += 1;

            $create_type = $v['create_type'];
            $title       = isset($v['title']) && $v['title'] ? $v['title'] : $v['field'];

            if (isset($v['attr']) && in_array('required', $v['attr'])) {
                if ($validate_count == 0) {
                    $validate .= <<<EOT
    '{$v['field']}|{$v['title']}' => 'require',

EOT;
                } else {
                    $validate .= <<<EOT
                '{$v['field']}|{$v['title']}' => 'require',

EOT;
                }
                $validate_count += 1;
            }

        }
        if ($only) {
            $only .= <<<EOT


EOT;
        }
        if ($validate) {
            $validate .= <<<EOT


EOT;
        }
        return ['only' => trim($only, PHP_EOL), 'validate' => trim($validate, PHP_EOL)];
    }

    /**
     * 获取with关联信息
     * @Author   July
     * @DateTime 2023-12-17T16:52:27+0800
     * @param    array                   $data 当前表格信息
     * @return   string                        关联信息字符串
     */
    private function getRelationWiths($data)
    {
        $where                  = [];
        $where['table_name']    = $data['name'];
        $where['relation_type'] = 'with';
        $withs                  = model\ModelRelation::where($where)->column('relation_name');
        if ($withs) {
            array_walk($withs, function (&$value, $key) {
                $value = "'" . $value . "'";
            });
        }
        return implode(',', $withs);
    }

    /**
     * 获取join关联信息
     * @Author   July
     * @DateTime 2023-12-17T16:52:27+0800
     * @param    array                   $data 当前表格信息
     * @return   string                        关联信息字符串
     */
    private function getRelationWithJoins($data)
    {
        $where   = [];
        $where[] = ['table_name', '=', $data['name']];
        $where[] = ['relation_type', '<>', 'with'];
        $withs   = model\ModelRelation::where($where)->select();
        $value   = [];
        if ($withs) {
            foreach ($withs as $k => $v) {
                $value[] = "'" . $v['relation_name'] . "' => '{$v['relation_type']}'";
            }
        }
        return implode(',', $value);
    }

    /**
     * 保存
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param  integer $isEdit 是否是编辑 0否，1是
     */
    protected function save($isEdit)
    {
        $data = input('post.', []);
        try {
            $info = [
                'controller_position|控制器位置' => 'require',
            ];
            validate($info)->check($data);
        } catch (\think\exception\ValidateException $e) {
            $this->error($e->getError());
        }

        $pk       = input("get." . $this->getPk());
        $database = Config("database.connections.mysql.database");
        $find     = $this->dataModel->where([$this->getPk() => $pk])->find();

        $path = '../' . $data['controller_position'];
        //创建目录
        if (!is_readable($path)) {
            is_file($path) or mkdir($path, 0777, true);
            chmod($path, 0777);
        }

        //配置
        $configs = $this->getControllerSettings($find, $data);
        //控制器名称
        $controller_name = $this->camelize(substr_replace($find['name'], '', 0, strlen(Config('database.connections.mysql.prefix'))));
        //命名空间
        $namespace      = str_replace('/', '\\', $data['controller_position']);
        $model_position = str_replace('/', '\\', $data['model_position']);
        $template       = <<<EOT
<?php
{$data['controller_desc']}
namespace {$namespace};

use july\julyadmin\builder\\traits\HasBuilder;
use {$model_position}\\{$controller_name} as {$controller_name}Model;
use july\julyadmin\admin\controller\Common;

class {$controller_name} extends Common
{
{$configs}
}
EOT;
        //保存文件名
        $filename = $path . '/' . $controller_name . '.php';
        if (file_exists($filename)) {
            unlink($filename);
        }
        file_put_contents($filename, $template);
        $this->success('创建成功', '');

    }

}
